home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Source Code
/
Pascal
/
Snippets
/
PNL Libraries
/
MyStringIDs.p
< prev
next >
Wrap
Text File
|
1997-06-06
|
4KB
|
175 lines
unit MyStringIDs;
interface
uses
Types;
type
StringID = longint;
const
null_string_id = -1;
procedure StartupStringIDs;
function CreateStringID( const s: Str255; var id: StringID ): OSStatus;
procedure DestroyStringID( var id: StringID );
function GetStringID( id: StringID; var s: Str255 ): boolean;
function GetStrID( id: StringID ): Str255;
implementation
uses
Memory,
MyAssertions, MyStartup, MyMemory, MyLowLevel;
type
StringIDEntry = record
id: StringID;
hash: longint;
reference_count: longint;
data: Str255; { packed, pad to 4 byte boundary }
end;
StringIDEntryPtr = ^StringIDEntry;
const
string_id_entry_base_length = SizeOf(StringIDEntry) - 256;
{$ifc do_debug}
var
startup_check: integer;
{$endc}
var
strings: Handle;
strings_count: longint;
current_id: longint;
function HashString( const s:Str255 ): longint;
var
value: longint;
i: integer;
begin
value := 0;
for i := 1 to length(s) do begin
value := value * 53 + ord(s[i]);
end;
HashString := band(value, $7FFFFFFF);
end;
function EntryLength( var entry: StringIDEntry ): longint;
begin
EntryLength := string_id_entry_base_length + ((1+length(entry.data) + 3) div 4 * 4);
end;
function FindID( id: StringID ): StringIDEntryPtr;
var
sep: StringIDEntryPtr;
i: longint;
begin
sep := StringIDEntryPtr(strings^);
for i := 1 to strings_count do begin
if sep^.id = id then begin
FindID := sep;
Exit(FindID);
end;
OffsetPtr( sep, EntryLength( sep^ ) );
end;
FindID := nil;
end;
function CreateStringID( const s: Str255; var id: StringID ): OSStatus;
var
i: longint;
err: OSErr;
hash: longint;
sep: StringIDEntryPtr;
entry: StringIDEntry;
begin
AssertDidStartup( startup_check );
id := null_string_id;
hash := HashString( s );
sep := StringIDEntryPtr(strings^);
for i := 1 to strings_count do begin
if (sep^.hash = hash) & (sep^.data = s) then begin
Inc(sep^.reference_count);
id := sep^.id;
CreateStringID := noErr;
Exit(CreateStringID);
end;
OffsetPtr( sep, EntryLength( sep^ ) );
end;
Inc(current_id);
Assert( (FindID( current_id ) = nil) );
entry.id := current_id;
entry.hash := hash;
entry.reference_count := 1;
entry.data := s;
err := PtrAndHand( @entry, strings, EntryLength( entry ) );
if err = noErr then begin
Inc(strings_count);
id := entry.id;
end;
CreateStringID := err;
end;
procedure DestroyStringID( var id: StringID );
var
sep: StringIDEntryPtr;
begin
AssertDidStartup( startup_check );
sep := FindID( id );
Assert( sep <> nil );
if sep <> nil then begin
Dec(sep^.reference_count);
if sep^.reference_count = 0 then begin
MMungerDelete( strings, SubPtrPtr( sep, strings^ ), EntryLength( sep^ ) );
Dec(strings_count);
end;
end;
id := null_string_id;
end;
function GetStringID( id: StringID; var s: Str255 ): boolean;
var
sep: StringIDEntryPtr;
begin
AssertDidStartup( startup_check );
sep := FindID( id );
GetStringID := sep <> nil;
if sep <> nil then begin
s := sep^.data;
end else begin
s := '';
end;
end;
function GetStrID( id: StringID ): Str255;
var
junk_boolean: boolean;
s: Str255;
begin
Assert( FindID( id ) <> nil );
junk_boolean := GetStringID( id, s );
GetStrID := s;
end;
function InitStringIDs( var msg: integer ): OSStatus;
begin
{$unused(msg)}
DidStartup( startup_check );
Assert( SizeOf( StringID ) = 4 );
strings_count := 0;
current_id := 1;
InitStringIDs := MNewHandle( strings, 0 );
end;
procedure StartupStringIDs;
begin
SetStartup( InitStringIDs, nil, 0, nil );
end;
end.